package lowijs.XfDroid;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

import lowijs.XfireClient.IM;
import lowijs.util.logging.Logging;
import android.content.ContentValues;
import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import android.database.CursorWrapper;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class FriendDBAdapter {
	private static final int DATABASE_VERSION = 6;

	private static final String DATABASE_NAME = "xfire";

	private static final String DATABASE_MEMBER = "member";

	private static final String DATABASE_FRIEND = "friend";

	private static final String DATABASE_WHO = "who";

	private static final String DATABASE_CHANNEL = "channel";

	private static final String DATABASE_MESSAGE = "message";

	private static final String DATABASE_VIEW_FRIEND = "my_friends";

	private static final String DATABASE_VIEW_MESAGE = "view_message";

	private static final String DATABASE_VIEW_WHO = "view_who";

	private static final String DATABASE_WATCH = "watch";

	// long row id
	public static final String KEY_ROWID = "_id";

	// long
	public static final String KEY_USERID = "userid";

	// String
	public static final String KEY_USERNAME = "username";

	// String
	public static final String KEY_NICKNAME = "nickname";

	// String
	public static final String KEY_STATUSTEXT = "statustext";

	// String
	public static final String KEY_ONLINE = "online";

	// String
	public static final String KEY_GAMEID = "gameid";

	// Blob
	public static final String KEY_SID = "sid";

	// long
	public static final String KEY_LOGONID = "logonid";

	// long
	public static final String KEY_FRIENDID = "friendid";

	// long
	public static final String KEY_MESSAGE = "message";

	// long
	public static final String KEY_CHANNEL = "channel";

	// long
	public static final String KEY_IMINDEX = "imindex";

	// long
	public static final String KEY_CHANNEL_ID = "channel_id";

	// long
	public static final String KEY_POSTED = "posted";

	// long
	public static final String KEY_KEY = "key";

	public static final String KEY_OWNERID = "ownerid";

	public static final String KEY_VALUE = "value";

	public static final String KEY_TYPE = "type";

	public static final int OFFLINE_FLAG = 0;

	public static final int ONLINE_FLAG = 1;

	private static FriendDBAdapter INSTANCE = new FriendDBAdapter();

	private static int ID = 1;

	private DatabaseHelper DBHelper;

	private SQLiteDatabase db;

	private TreeMap<CursorType, Set<StatusWatcher>> watches;

	private FriendDBAdapter() {
	}

	class StatusWatcher extends CursorWrapper implements Comparable<StatusWatcher> {
		private List<ContentObserver> content;

		private int id;

		private CursorType type;

		public StatusWatcher(Cursor cursor, CursorType type) {
			super(cursor);
			id = ID++;
			this.type = type;

			content = new ArrayList<ContentObserver>();
			add(this, type);
		}

		@Override
		public void registerContentObserver(ContentObserver observer) {
			super.registerContentObserver(observer);
			content.add(observer);
		}

		@Override
		public void unregisterContentObserver(ContentObserver observer) {
			super.unregisterContentObserver(observer);
			content.remove(observer);
		}

		@Override
		public void deactivate() {
			remove(this, type);
			super.deactivate();
		}

		@Override
		public boolean requery() {
			add(this, type);
			return super.requery();
		}

		public int compareTo(StatusWatcher another) {
			return id - another.id;
		}

		public void contentChanged() {
			for (ContentObserver c : content) {
				c.dispatchChange(false);
			}
		}
	}

	private static class DatabaseHelper extends SQLiteOpenHelper {
		DatabaseHelper(Context context) {
			super(context, DATABASE_NAME, null, DATABASE_VERSION);
		}

		@Override
		public void onCreate(SQLiteDatabase db) {
			System.out.println("Create: " + DATABASE_VERSION + ";");
			runScript(db, "lowijs/XfDroid/create.sql");
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			System.out.println("Old Version: " + oldVersion + "; New Version: " + newVersion + ";");
			runScript(db, "lowijs/XfDroid/update6.sql");
			for (int i=oldVersion+1; i<=newVersion; i++) {
				runScript(db, "lowijs/XfDroid/update" + i + ".sql");
			}
		}

		private void runScript(SQLiteDatabase db, String resName) {
			ClassLoader loader = FriendDBAdapter.class.getClassLoader();
			URL url = loader.getResource(resName);
			if (url != null) {
				try {
					BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
					try {
						while (true) {
							String line = reader.readLine();
							if (line == null) break;
							if (line.trim().length() == 0) continue;
							db.execSQL(line);
							System.out.println("EXEC: " + line);
						}
					} catch (Exception e) {
						reader.close();
					}
				} catch (Exception e) {
					Logging.getLogging().clientException("Failed to run database scripts", e);
				}
			}
		}
	}

	protected void add(StatusWatcher watcher, CursorType type) {
		Set<StatusWatcher> set = watches.get(type);

		if (set == null) {
			set = new TreeSet<StatusWatcher>();
			watches.put(type, set);
		}

		set.add(watcher);
	}

	protected void remove(StatusWatcher watcher, CursorType type) {
		Set<StatusWatcher> set = watches.get(type);

		if (set == null) {
			return;
		}

		set.remove(watcher);
	}

	// ---opens the database---
	public FriendDBAdapter open() throws SQLException {
		db = DBHelper.getWritableDatabase();
		return this;
	}

	// ---closes the database---
	public void close() {
		DBHelper.close();
	}

	public void init(Context context) {
		if (db == null) {
			DBHelper = new DatabaseHelper(context);
			watches = new TreeMap<CursorType, Set<StatusWatcher>>();

			try {
				open();

				ContentValues values = new ContentValues();
				values.putNull(KEY_SID);
				values.put(KEY_ONLINE, OFFLINE_FLAG);
				values.put(KEY_STATUSTEXT, "Offline");
				values.put(KEY_GAMEID, "Offline");
				db.update(DATABASE_MEMBER, values, null, null);

				values = new ContentValues();
				values.put(KEY_LOGONID, -1);
				db.update(DATABASE_WHO, values, null, null);
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	public long findMemberBySid(byte[] sid) {
		long id = -1;

		Cursor c = db.query(DATABASE_MEMBER, new String[] {KEY_ROWID}, KEY_SID + "=?", new String[] {toString(sid)}, null, null, null);

		if (c.moveToFirst()) {
			id = c.getLong(0);
		}

		c.close();

		return id;
	}

	public long findMemberById(long userid) {
		long id = -1;

		Cursor c = db.query(DATABASE_MEMBER, new String[] {KEY_ROWID}, KEY_USERID + "=" + Long.toString(userid), null, null, null, null);

		if (c.moveToFirst()) {
			id = c.getLong(0);
		}

		c.close();

		return id;
	}

	public long findMemberByName(String username) {
		long id = -1;

		Cursor c = db.query(DATABASE_MEMBER, new String[] {KEY_ROWID}, KEY_USERNAME + "=?", new String[] {username}, null, null, null);

		if (c.moveToFirst()) {
			id = c.getLong(0);
		}

		c.close();

		return id;
	}

	public long insertMember(long userid, String username, String nickname, String statustext, int online) {
		if (nickname == null || nickname.trim().length() == 0) {
			nickname = username;
		}

		ContentValues initialValues = new ContentValues();
		initialValues.put(KEY_USERID, userid);
		initialValues.put(KEY_USERNAME, username);
		initialValues.put(KEY_NICKNAME, nickname);
		initialValues.put(KEY_STATUSTEXT, statustext);
		initialValues.put(KEY_GAMEID, 0);
		initialValues.put(KEY_ONLINE, online);
		return db.insert(DATABASE_MEMBER, null, initialValues);
	}

	public long updateMember(long rowid, long userid, String username, String nickname, String statustext, int online) {
		if (nickname == null || nickname.trim().length() == 0) {
			nickname = username;
		}

		ContentValues initialValues = new ContentValues();
		initialValues.put(KEY_USERID, userid);
		initialValues.put(KEY_USERNAME, username);
		initialValues.put(KEY_NICKNAME, nickname);
		initialValues.put(KEY_STATUSTEXT, statustext);
		initialValues.put(KEY_GAMEID, 0);
		initialValues.put(KEY_ONLINE, online);
		return db.update(DATABASE_MEMBER, initialValues, "_id=" + Long.toString(rowid), null);
	}

	public boolean deleteMember(long rowId) {
		return db.delete(DATABASE_MEMBER, KEY_ROWID + "=" + rowId, null) > 0;
	}

	public long findFriend(long logonRowid, long friendRowid) {
		long id = -1;

		Cursor c = db.query(DATABASE_FRIEND, new String[] {KEY_ROWID}, KEY_LOGONID + "=" + Long.toString(logonRowid) + " AND " + KEY_FRIENDID + "=" + Long.toString(friendRowid), null, null, null, null);

		if (c.moveToFirst()) {
			id = c.getLong(0);
		}

		c.close();
		return id;
	}

	public void login(int userid, String username, String nickname, byte[] sid) {
		long id = findMemberById(userid);

		if (id == -1) {
			// insert
			id = insertMember(userid, username, nickname, "Android Online", ONLINE_FLAG);
		} else {
			// update
			updateMember(id, userid, username, nickname, "Android Online", ONLINE_FLAG);
		}

		ContentValues initialValues = new ContentValues();
		initialValues.put(KEY_LOGONID, id);
		db.update(DATABASE_WHO, initialValues, null, null);

		update(CursorType.STATUS);
		update(CursorType.CURRENT);
	}

	public void nickname(String nickname) {
		ContentValues values = new ContentValues();
		values.put(KEY_NICKNAME, nickname);
		db.update(DATABASE_MEMBER, values, KEY_USERID + "=" + getMyid(), null);

		update(CursorType.STATUS);
		update(CursorType.CURRENT);
	}

	public long insertFriend(long logonid, long friendid) {
		ContentValues initialValues = new ContentValues();
		initialValues.put(KEY_LOGONID, logonid);
		initialValues.put(KEY_FRIENDID, friendid);
		return db.insert(DATABASE_FRIEND, null, initialValues);
	}

	public boolean deleteFriend(long rowId) {
		return db.delete(DATABASE_FRIEND, KEY_ROWID + "=" + rowId, null) > 0;
	}

	public Cursor getOnlineFriends() {
		return new StatusWatcher(db.query(DATABASE_VIEW_FRIEND, new String[] {KEY_ROWID, KEY_USERNAME, KEY_NICKNAME, KEY_STATUSTEXT, KEY_GAMEID, KEY_ONLINE}, KEY_ONLINE + "=" + ONLINE_FLAG, null, null, null, KEY_NICKNAME), CursorType.STATUS);
	}

	public Cursor getOfflineFriends() {
		return new StatusWatcher(db.query(DATABASE_VIEW_FRIEND, new String[] {KEY_ROWID, KEY_USERNAME, KEY_NICKNAME, KEY_STATUSTEXT, KEY_GAMEID, KEY_ONLINE}, KEY_ONLINE + "=" + OFFLINE_FLAG, null, null, null, KEY_NICKNAME), CursorType.STATUS);
	}

	public Cursor getAllFriends() {
		return new StatusWatcher(db.query(DATABASE_VIEW_FRIEND, new String[] {KEY_ROWID, KEY_USERNAME, KEY_NICKNAME, KEY_STATUSTEXT, KEY_GAMEID, KEY_ONLINE},  null, null, null, null, KEY_ONLINE + " DESC" + ", " + KEY_NICKNAME), CursorType.STATUS);
	}

	public void manageFriend(String[] usernames, String[] nicknames, int[] userids) {
		long myid = getMyid();

		for (int i=0, n=usernames.length; i<n; i++) {
			int userid = userids[i];

			long id = findMemberById(userid);

			if (id == -1) {
				// insert
				id = insertMember(userid, usernames[i], nicknames[i], "Offline", OFFLINE_FLAG);
			} else {
				// update
				updateMember(id, userid, usernames[i], nicknames[i], "Offline", OFFLINE_FLAG);
			}

			if (findFriend(myid, id) == -1) {
				insertFriend(myid, id);
			}
		}

		update(CursorType.STATUS);
	}

	public long getMyid() {
		long id = -1;

		Cursor c = db.query(DATABASE_WHO, new String[] {KEY_LOGONID}, null, null, null, null, null);

		if (c.moveToFirst()) {
			id = c.getLong(0);
		}

		c.close();

		return id;
	}

	public void offline(long id) {
		ContentValues values = new ContentValues();
		values.putNull(KEY_SID);
		values.put(KEY_ONLINE, OFFLINE_FLAG);
		values.put(KEY_STATUSTEXT, "Offline");
		values.put(KEY_GAMEID, 0);
		db.update(DATABASE_MEMBER, values, KEY_ROWID + "=" + Long.toString(id), null);
		update(CursorType.STATUS);
	}

	public void online(long id, byte[] sid) {
		ContentValues values = new ContentValues();
		values.put(KEY_SID, toString(sid));
		values.put(KEY_ONLINE, ONLINE_FLAG);
		values.put(KEY_STATUSTEXT, "Online");
		values.put(KEY_GAMEID, 0);
		db.update(DATABASE_MEMBER, values, KEY_ROWID + "=" + Long.toString(id), null);
		update(CursorType.STATUS);
	}

	public String[] status(long[] id, byte[][] sids) {
		ContentValues values = new ContentValues();
		String[] result = new String[id.length];

		for (int i=0, n=id.length; i<n; i++) {
			int status = OFFLINE_FLAG;

			if (sids[i] == null || isZero(sids[i])) {
				values.putNull(KEY_SID);
				values.put(KEY_STATUSTEXT, "Offline");
				values.put(KEY_ONLINE, status);
			} else {
				status = ONLINE_FLAG;
				values.put(KEY_SID, toString(sids[i]));
				values.put(KEY_STATUSTEXT, "Online");
				values.put(KEY_ONLINE, status);
			}
			long rowid = findMemberById(id[i]);
			db.update(DATABASE_MEMBER, values, KEY_ROWID + "=" + rowid, null);
			String nickname = nickname(rowid);
			result[i] = rowid + ":" + status + ":" + nickname;
		}

		update(CursorType.STATUS);
		return result;
	}

	public void status(byte[][] sids, String[] status) {
		ContentValues values = new ContentValues();

		for (int i=0, n=sids.length; i<n; i++) {
			values.put(KEY_STATUSTEXT, status[i]);
			db.update(DATABASE_MEMBER, values, KEY_SID + "=?", new String[] {toString(sids[i])});
		}

		update(CursorType.STATUS);
	}

	private boolean isZero(byte[] bs) {
		for (byte b : bs) {
			if (b != 0) {
				return false;
			}
		}

		return true;
	}

	private void update(CursorType type) {
		Set<StatusWatcher> set = watches.get(type);

		if (set != null) {
			for (StatusWatcher c : set) {
				c.contentChanged();
			}
		}
	}

	public static String toString(byte[] sid) {
		if (sid == null) {
			return "Nil";
		}

		StringBuilder builder = new StringBuilder();
		for (byte b : sid) {
			String t = Integer.toHexString((int)(b&0xFF));
			if (t.length() == 1) {
				builder.append("0");
			}
			builder.append(t);
		}

		return builder.toString();
	}

	public IM postMessage(long channelid, String message) {
		long time = System.currentTimeMillis();

		Cursor c = db.rawQuery("SELECT MAX(imindex) FROM message WHERE channel_id=" + channelid, null);
		c.moveToFirst();
		int imindex = c.getInt(0) + 1;
		c.close();

		String key = null;

		c = db.query(DATABASE_CHANNEL, new String[] {KEY_KEY}, KEY_ROWID + "=" + channelid, null, null, null, null);

		if (c.moveToFirst()) {
			key = c.getString(0);
		}

		c.close();

		if (key == null) {
			throw new IllegalArgumentException("Channel does not exist " + channelid);
		}

		String sidtxt = null;
		int online = OFFLINE_FLAG;

		if (key.startsWith("user:")) {
			long rowid = Long.parseLong(key.substring(5));
			c = db.query(DATABASE_MEMBER, new String[] {KEY_SID, KEY_ONLINE}, KEY_ROWID + "=" + rowid, null, null, null, null);

			if (c.moveToFirst()) {
				sidtxt = c.getString(0);
				online = c.getInt(1);
			}

			c.close();
		}

		if (sidtxt == null || online == OFFLINE_FLAG) {
			return null;
		}

		byte[] sid = toBytes(sidtxt);

		c = db.query(DATABASE_WHO, new String[] {KEY_LOGONID}, null, null, null, null, null);
		c.moveToFirst();
		long myid = c.getLong(0);
		c.close();

		c = db.query(DATABASE_MEMBER, new String[] {KEY_NICKNAME}, KEY_ROWID + "=" + myid, null, null, null, null);
		c.moveToFirst();
		String nick = c.getString(0);
		c.close();

		ContentValues values = new ContentValues();
		values.put(KEY_CHANNEL_ID, channelid);
		values.put(KEY_USERID, myid);
		values.put(KEY_MESSAGE, message);
		values.put(KEY_IMINDEX, imindex);
		values.put(KEY_POSTED, time);
		db.insert(DATABASE_MESSAGE, null, values);

		update(CursorType.CHANNEL);
		return new IM(channelid, myid, nick, message, sid, imindex);
	}

	private byte[] toBytes(String sidtxt) {
		if (sidtxt == null || sidtxt.equals("Nil")) {
			return null;
		}

		byte[] sid = new byte[16];

		for (int i=0, n=sidtxt.length(), j=0; i<n; i+=2, j++) {
			String code = sidtxt.substring(i, i+2);
			sid[j] = (byte)(Integer.parseInt(code, 16) & 0xFF);
		}

		return sid;
	}

	public IM postMessage(byte[] sid, String message, int imindex) {
		long rowid = -1;
		String nick = "Unknown";

		// Get userid and nickname
		Cursor c = db.query(DATABASE_MEMBER, new String[] {KEY_ROWID, KEY_NICKNAME}, KEY_SID + "=?", new String[] {toString(sid)}, null, null, null);

		if (c.moveToFirst()) {
			rowid = c.getLong(0);
			nick = c.getString(1);
		}

		c.close();

		// Get channelId
		long channelId = -1;

		try {
			channelId = openChannel(rowid);
		} catch (SQLException e) {
		}

		long time = System.currentTimeMillis();

		ContentValues values = new ContentValues();
		values.put(KEY_CHANNEL_ID, channelId);
		values.put(KEY_USERID, rowid);
		values.put(KEY_MESSAGE, message);
		values.put(KEY_IMINDEX, imindex);
		values.put(KEY_POSTED, time);
		db.insert(DATABASE_MESSAGE, null, values);

		update(CursorType.CHANNEL);
		return new IM(channelId, rowid, nick, message, sid, imindex);
	}

	public Cursor channelMembers(long channelid) {
		long rowid = -1;
		Cursor c = db.query(DATABASE_CHANNEL, new String[] {KEY_KEY}, KEY_ROWID + "=" + channelid, null, null, null, null);
		if (c.moveToFirst()) {
			String key = c.getString(0);

			if (key.startsWith("user:")) {
				rowid = Long.parseLong(key.substring(5));
			}
		}
		c.close();

		c = db.query(DATABASE_MEMBER, new String[] {KEY_ROWID, KEY_ONLINE}, KEY_ROWID + "=" + rowid, null, null, null, null);
		return new StatusWatcher(c, CursorType.STATUS);
	}

	public Cursor channel(long channelid) {
		Cursor c = db.query(DATABASE_VIEW_MESAGE, new String[] {KEY_ROWID, KEY_USERID, KEY_MESSAGE, KEY_POSTED, KEY_NICKNAME, KEY_IMINDEX}, KEY_CHANNEL_ID + "=" + channelid, null, null, null, KEY_POSTED);
		return new StatusWatcher(c, CursorType.CHANNEL);
	}

	public long openChannel(long rowid) throws SQLException {
		long channelid = -1;

		long userid = -1;
		String sid = null;
		int online = OFFLINE_FLAG;
		String nickname = null;

		Cursor c = db.query(DATABASE_MEMBER, new String[] {KEY_ROWID, KEY_SID, KEY_ONLINE, KEY_NICKNAME}, KEY_ROWID + "=" + rowid, null, null, null, null);
		if (c.moveToFirst()) {
			userid = c.getLong(0);
			sid = c.getString(1);
			online = c.getInt(2);
			nickname = c.getString(3);
		}
		c.close();

		String key = "user:" + userid;
		long myid = getMyid();

		c = db.query(DATABASE_CHANNEL, new String[] {KEY_ROWID}, KEY_KEY + "=? AND " + KEY_OWNERID + "=" + myid, new String[] {key}, null, null, null);
		if (c.moveToFirst()) {
			channelid = c.getLong(0);
		}
		c.close();

		if (online != OFFLINE_FLAG) {
			if (channelid == -1) {
				ContentValues values = new ContentValues();
				values.put(KEY_CHANNEL, nickname);
				values.put(KEY_KEY, key);
				values.put(KEY_OWNERID, myid);
				channelid = db.insert(DATABASE_CHANNEL, null, values);
			} else {
				ContentValues values = new ContentValues();
				values.put(KEY_CHANNEL, nickname);
				db.update(DATABASE_CHANNEL, values, KEY_ROWID + "=" + channelid, null);
			}

			if (channelid == -1) {
				throw new SQLException("Could not insert channel " + nickname + ", " + key + ", " + sid);
			}
		}

		return channelid;
	}

	public void updateGames(long[] friends, long[] gameids) {
		ContentValues values = new ContentValues();

		for (int i=0, n=friends.length; i<n; i++) {
			values.put(KEY_GAMEID, gameids[i]);
			db.update(DATABASE_MEMBER, values, KEY_ROWID + "=" + friends[i], null);
		}

		update(CursorType.STATUS);
	}

	public Cursor current() {
		Cursor c = db.query(DATABASE_VIEW_WHO, new String[] {KEY_ROWID, KEY_USERID, KEY_NICKNAME, KEY_STATUSTEXT}, null, null, null, null, null);
		return new StatusWatcher(c, CursorType.CURRENT);
	}

	public String channelname(long channelid) {
		Cursor c = db.query(DATABASE_CHANNEL, new String[] {KEY_CHANNEL}, KEY_ROWID + "=" + channelid, null, null, null, null);
		c.moveToFirst();
		String name = c.getString(0);
		c.close();
		return name;
	}

	public static FriendDBAdapter getInstance(Context context) {
		INSTANCE.init(context);

		return INSTANCE;
	}

	public void notify(long channelid, long userid, boolean online) {
		String status = "is now offline";

		if (online) {
			status = "is now online";
		}

		long time = System.currentTimeMillis();

		ContentValues values = new ContentValues();
		values.put(KEY_CHANNEL_ID, channelid);
		values.put(KEY_USERID, userid);
		values.put(KEY_MESSAGE, status);
		values.put(KEY_IMINDEX, -9999);
		values.put(KEY_POSTED, time);
		db.insert(DATABASE_MESSAGE, null, values);

		update(CursorType.CHANNEL);
	}

	public void gamename(int gameid, String str) {
		ContentValues values = new ContentValues();
		values.put("gamename", str);

		if (db.update("game", values, "gameid=" + gameid, null) == 0) {
			values.put("gameid", gameid);
			db.insert("game", null, values);
		}
	}

	public String username(long rowid) {
		String un = null;
		Cursor c = db.query(DATABASE_MEMBER, new String[] {KEY_USERNAME}, KEY_ROWID + "=" + rowid, null, null, null, null);
		if (c.moveToFirst()) {
			un = c.getString(0);
		}
		c.close();
		return un;
	}

	public String nickname(long rowid) {
		String un = null;
		Cursor c = db.query(DATABASE_MEMBER, new String[] {KEY_NICKNAME}, KEY_ROWID + "=" + rowid, null, null, null, null);
		if (c.moveToFirst()) {
			un = c.getString(0);
		}
		c.close();
		return un;
	}

	public CharSequence gamename(long rowid) {
		String un = null;
		Cursor c = db.query("game", new String[] {"gamename"}, "gameid=" + rowid, null, null, null, null);
		if (c.moveToFirst()) {
			un = c.getString(0);
		}
		c.close();
		return un;
	}

	public int userid(long rowid) {
		int un = 0;
		Cursor c = db.query(DATABASE_MEMBER, new String[] {KEY_USERID}, KEY_ROWID + "=" + rowid, null, null, null, null);
		if (c.moveToFirst()) {
			un = c.getInt(0);
		}
		c.close();
		return un;
	}

	public boolean isPersistent(long userid, int online) {
		int type = 2;

		if (online == OFFLINE_FLAG) {
			type = 1;
		}

		boolean watched = false;

		Cursor c = db.query(DATABASE_WATCH, new String[] {KEY_VALUE}, KEY_USERID + "=" + userid + " AND " + KEY_LOGONID + "=" + getMyid() + " AND type=" + type, null, null, null, null);
		if (c.moveToFirst()) {
			watched = c.getInt(0) != 0;
		}
		c.close();

		return watched;
	}

	public Map<Integer, Integer> getNotifications(long userid) {
		Map<Integer, Integer> map = new TreeMap<Integer, Integer>();

		Cursor c = db.query(DATABASE_WATCH, new String[] {KEY_TYPE, KEY_VALUE}, KEY_USERID + "=" + userid + " AND " + KEY_LOGONID + "=" + getMyid(), null, null, null, null);
		while (c.moveToNext()) {
			map.put(c.getInt(0), c.getInt(1));
		}
		c.close();

		return map;
	}

	public void toggleWatch(long userid, int type) {
		long myid = getMyid();
		long rowid = -1;
		int value = 0;

		Cursor c = db.query(DATABASE_WATCH, new String[] {KEY_ROWID, KEY_VALUE}, KEY_USERID + "=" + userid + " AND " + KEY_LOGONID + "=" + myid + " AND type=" + type, null, null, null, null);
		if (c.moveToNext()) {
			rowid = c.getLong(0);
			value = c.getInt(1);
		}
		c.close();

		if (value == 0) {
			value = 1;
		} else {
			value = 0;
		}

		if (rowid == -1) {
			ContentValues values = new ContentValues();
			values.put(KEY_USERID, userid);
			values.put(KEY_LOGONID, myid);
			values.put(KEY_TYPE, type);
			values.put(KEY_VALUE, value);
			db.insert(DATABASE_WATCH, null, values);
		} else {
			ContentValues values = new ContentValues();
			values.put(KEY_VALUE, value);
			db.update(DATABASE_WATCH, values, KEY_ROWID + "=" + rowid, null);
		}
	}
}
